import Constant from './constant'

export default class Paint {
  constructor(basicCesium) {
    this.cesiumContainer = document.querySelector('#cesium');
    this.basicCesium = basicCesium
    this.viewer = basicCesium.viewer;

    this.mp = null
    this.mpArray = []
    this.mpArrayLen = 0
    this.currentEntity = null
    this.markEventObj = {
      isMarkPoint: {
        enable: false,
        fn: basicCesium.entityPoint.bind(basicCesium)
      },
      isMarkPolyline: {
        enable: false,
        fn: basicCesium.entityPolyline.bind(basicCesium)
      },
      isMarkPolygon: {
        enable: false,
        fn: basicCesium.entityPolygon.bind(basicCesium)
      },
      isMarkCircle: {
        enable: false,
        fn: basicCesium.entityCircle.bind(basicCesium)
      },
      isMarkRectangle: {
        enable: false,
        fn: basicCesium.entityRectangle.bind(basicCesium)
      }
    }

    this.initTips();
    this.initEvent()
  }

  //鼠标事件 
  initEvent() {
    let viewer = this.viewer;
    let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
    handler.setInputAction((e) => {
      console.log('left click')
      //点击位置坐标
      this.mp = e.position;
      let cartesian3 = this.basicCesium.xyToWorld(e.position)
      if (this.isHandleMark()) {
        if (this.mpArray.length == this.mpArrayLen) {
          this.mpArray.push(cartesian3)
        } else {
          this.mpArray.splice(this.mpArrayLen, 1, cartesian3)
        }
        this.mpArrayLen = this.mpArray.length
        this.handleMarkEvent('left_click');
      }
      this.basicCesium.getMouseInfo(e.position);
      this.removeMenu()
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    handler.setInputAction((e) => {
      console.log('right click')
      //点击位置坐标
      this.mp = e.position;
      this.loadUi(e.position, Constant.PAINT)

      if (this.isHandleMark()) {
        let len = this.mpArray.length
        this.mpArray.splice(len - 2, 2)
        this.mpArrayLen = this.mpArray.length
        this.handleMarkEvent('right_click');
      }
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

    handler.setInputAction((e) => {
      console.log('left double click')
      if (this.isHandleMark()) {
        this.handleMarkEvent('left_double_click');
      }
    }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

    handler.setInputAction((e) => {
      console.log('mouse move')
      //点击位置坐标
      let cartesian3 = this.basicCesium.xyToWorld(e.endPosition)
      if (this.isHandleMark() && this.mpArrayLen >= 1) {
        if (this.mpArray.length == this.mpArrayLen) {
          this.mpArray.push(cartesian3)
        } else {
          this.mpArray.splice(this.mpArrayLen, 1, cartesian3)
        }
        this.handleMarkEvent('mouse_move');
      }

      this.changeTipsPosition(e.endPosition)
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  }

  loadUi(position, array) {
    if (this.isHandleMark()) return false
    let scene = this.viewer.scene;
    let str = '';
    let filter = []
    let x = position.x + 6;
    let y = position.y + 6;
    let width = scene.canvas.width;
    let height = scene.canvas.height;
    let isAlignBottom = false;
    let isAlignLeft = false;
    if (x > width - 140) {
      x = width - 140;
      isAlignLeft = true;
    } else if (x > width - 268) {
      isAlignLeft = true;
    } else if (x < 12) {
      x = 12;
    }
    if (y > height - 69) {
      y = height - 69;
      isAlignBottom = true;
    } else if (y < 12) {
      y = 12;
    }

    str = this.renderMenu(array, filter, isAlignBottom, isAlignLeft);
    let divs = document.querySelectorAll('.context-menu');
    if (divs != undefined && divs.length != 0) {
      this.cesiumContainer.removeChild(divs[0])
    }

    let div = document.createElement('div')
    div.className = 'context-menu'
    div.style.top = y + 'px'
    div.style.left = x + 'px'
    div.style.position = 'absolute'
    div.innerHTML = `<ul class="menu-list">${str}</ul>`
    this.cesiumContainer.append(div);
  }

  renderMenu(array, filter = [], isAlignBottom, isAlignLeft) {
    let list = [];
    let ul = '';
    window.rightClick = this.rightClick.bind(this);

    if (isAlignBottom && isAlignLeft) {
      ul = `<ul class="menu-list" style="bottom: 0;left:-138px">`
    } else if (isAlignBottom && !isAlignLeft) {
      ul = `<ul class="menu-list" style="bottom: 0px;left:128px">`
    } else if (!isAlignBottom && isAlignLeft) {
      ul = `<ul class="menu-list" style="top: 0;left:-138px">`
    } else if (!isAlignBottom && !isAlignLeft) {
      ul = `<ul class="menu-list" style="top: 0;left:128px">`
    }

    for (let i = 0; i < array.length; i++) {
      if (array[i].children) {
        list.push(`<li class="menu-list-item has-child"><div class="event">${array[i].text}</div>${ul}`)
        let children = array[i].children;
        for (let k = 0; k < children.length; k++) {
          if (filter.indexOf(children[k].type) > -1) {
            continue;
          }
          list.push(`<li class="menu-list-item last-leaf"><div class="event" onclick="rightClick('${children[k].type}')">${children[k].text}</div></li>`)
        }
        list.push('</ul></li>')
      } else {
        if (filter.indexOf(array[i].type) > -1) {
          continue;
        }
        list.push(`<li class="menu-list-item no-child"><div class="event" onclick="rightClick('${array[i].type}')">${array[i].text}</div></li>`)
      }
    }
    return list.join('');
  }

  rightClick(type) {
    let viewer = this.viewer;
    this.mpArray = []
    this.mpArrayLen = 0
    this.removeTips();
    console.log('right click = ', type);
    switch (type) {
      case 'point':
        viewer._container.style.cursor = 'crosshair'
        this.setMarkEvent('isMarkPoint')
        this.addTips('左键绘制点');
        break;
      case 'polyline':
        viewer._container.style.cursor = 'crosshair'
        this.setMarkEvent('isMarkPolyline')
        this.addTips('左键绘制，右键回退，双击结束操作');
        break;
      case 'polygon':
        viewer._container.style.cursor = 'crosshair'
        this.setMarkEvent('isMarkPolygon')
        this.addTips('左键绘制，右键回退，双击结束操作');
        break;
      case 'circle':
        viewer._container.style.cursor = 'crosshair'
        this.setMarkEvent('isMarkCircle')
        this.addTips('左键绘制，右键回退');
        break;
      case 'rectangle':
        viewer._container.style.cursor = 'crosshair'
        this.setMarkEvent('isMarkRectangle')
        this.addTips('左键绘制，右键回退');
        break;
      case 'clearMarks':
        this.clearMarks();
        break;
    }
    this.removeMenu();
  }

  setMarkEvent(type) {
    for (let key in this.markEventObj) {
      this.markEventObj[key].enable = key === type
    }
  }

  isHandleMark() {
    let isBool = false
    for (let key in this.markEventObj) {
      if (this.markEventObj[key].enable) {
        isBool = true
      }
    }
    return isBool
  }

  handleMarkEvent(type) {
    for (let key in this.markEventObj) {
      if (this.markEventObj[key].enable) {
        if (key === 'isMarkPoint') {
          let data = this.basicCesium.xyToWorld(this.mp)
          switch (type) {
            case 'left_click':
              this.markEventObj[key].fn(data)
              break
            case 'right_click':
              this.markEventObj[key].enable = false
              this.removeTips()
              break
          }

        } else if (key === 'isMarkPolyline') {
          let data = this.mpArray
          switch (type) {
            case 'left_click':
              if (this.currentEntity != null && data.length > 1) {
                this.currentEntity.polyline.positions = new Cesium.CallbackProperty(() => {
                  return data;
                }, false)
              }
              break
            case 'right_click':
              if (this.currentEntity != null && data.length > 1) {
                this.currentEntity.polyline.positions = new Cesium.CallbackProperty(() => {
                  return data;
                }, false)
              } else if (data.length == 0 && this.currentEntity != null) {
                this.viewer.entities.remove(this.currentEntity)
                this.currentEntity = null
              }
              break
            case 'mouse_move':
              if (this.currentEntity == null && data.length == 2) {
                this.currentEntity = this.markEventObj[key].fn(data)
              } else if (this.currentEntity != null && data.length > 1) {
                this.currentEntity.polyline.positions = new Cesium.CallbackProperty(() => {
                  return data;
                }, false)
              }
              break
            case 'left_double_click':
              this.mpArray = []
              this.mpArrayLen = 0
              this.currentEntity = null
              this.markEventObj[key].enable = false
              this.removeTips()
              break
          }

        } else if (key === 'isMarkPolygon') {
          let data = this.mpArray
          switch (type) {
            case 'left_click':
              if (this.currentEntity != null && data.length > 2) {
                this.currentEntity.polygon.hierarchy = new Cesium.CallbackProperty(() => {
                  return new Cesium.PolygonHierarchy(data);
                }, false)
              }
              break
            case 'right_click':
              if (this.currentEntity != null && data.length > 2) {
                this.currentEntity.polygon.hierarchy = new Cesium.CallbackProperty(() => {
                  return new Cesium.PolygonHierarchy(data);
                }, false)
              } else if (data.length == 0 && this.currentEntity != null) {
                this.viewer.entities.remove(this.currentEntity)
                this.currentEntity = null
              }
              break
            case 'mouse_move':
              if (this.currentEntity == null && data.length == 3) {
                this.currentEntity = this.markEventObj[key].fn(data)
              } else if (this.currentEntity != null && data.length > 1) {
                this.currentEntity.polygon.hierarchy = new Cesium.CallbackProperty(() => {
                  return new Cesium.PolygonHierarchy(data);
                }, false)
              }
              break
            case 'left_double_click':
              this.mpArray = []
              this.mpArrayLen = 0
              this.currentEntity = null
              this.markEventObj[key].enable = false
              this.removeTips()
              break
          }

        } else if (key === 'isMarkCircle') {
          let data = this.mpArray
          switch (type) {
            case 'left_click':
              if (this.currentEntity != null && data.length == 2) {
                let radius = Cesium.Cartesian3.distance(data[0], data[1]);
                let cb = new Cesium.CallbackProperty(() => {
                  return radius;
                }, false);
                this.currentEntity.ellipse.semiMinorAxis = cb;
                this.currentEntity.ellipse.semiMajorAxis = cb;

                this.mpArray = []
                this.mpArrayLen = 0
                this.currentEntity = null
                this.markEventObj[key].enable = false
                this.removeTips()
              }
              break
            case 'right_click':
              if (data.length == 0 && this.currentEntity != null) {
                this.viewer.entities.remove(this.currentEntity)
                this.currentEntity = null
              }
              break
            case 'mouse_move':
              if (this.currentEntity == null && data.length == 2) {
                this.currentEntity = this.markEventObj[key].fn(data)
              } else if (this.currentEntity != null && data.length == 2) {
                let radius = Cesium.Cartesian3.distance(data[0], data[1]);
                let cb = new Cesium.CallbackProperty(() => {
                  return radius;
                }, false);
                this.currentEntity.ellipse.semiMinorAxis = cb;
                this.currentEntity.ellipse.semiMajorAxis = cb;
              }
              break
          }

        } else if (key === 'isMarkRectangle') {
          let data = this.mpArray
          switch (type) {
            case 'left_click':
              if (this.currentEntity != null && data.length == 2) {
                this.currentEntity.rectangle.coordinates = new Cesium.CallbackProperty(() => {
                  return Cesium.Rectangle.fromCartesianArray(data)
                }, false)

                this.mpArray = []
                this.mpArrayLen = 0
                this.currentEntity = null
                this.markEventObj[key].enable = false
                this.removeTips()
              }
              break
            case 'mouse_move':
              if (this.currentEntity == null && data.length == 2) {
                this.currentEntity = this.markEventObj[key].fn(data)
              } else if (this.currentEntity != null && data.length == 2) {
                this.currentEntity.rectangle.coordinates = new Cesium.CallbackProperty(() => {
                  return Cesium.Rectangle.fromCartesianArray(data)
                }, false)
              }
              break
          }

        }
      }
    }
  }

  //清空标记
  clearMarks() {
    this.viewer.entities.removeAll()
  }

  removeMenu() {
    let divs = document.querySelectorAll('.context-menu');
    if (divs != undefined && divs.length != 0) {
      this.cesiumContainer.removeChild(divs[0])
    }
  }

  initTips() {
    let div = document.createElement('div');
    div.id = 'tips';
    this.cesiumContainer.append(div);
  }

  changeTipsPosition(position) {
    let div = document.getElementById('tips');
    if (div == null) return false;
    if (div.style.display == 'none') return false;
    div.style.left = position.x + 15 + 'px';
    div.style.top = position.y + 'px';
  }


  addTips(text = '') {
    let div = document.getElementById('tips');
    if (div == null) return false;
    div.style.display = 'block'
    div.style.left = this.mp.x + 15 + 'px';
    div.style.top = this.mp.y + 'px';
    div.innerHTML = `<div>${text}</div>`
  }

  removeTips() {
    this.viewer._container.style.cursor = 'default'
    let div = document.getElementById('tips');
    if (div != null) {
      div.style.display = 'none'
      div.innerHTML = ''
    }
  }
}